/**
 * 区域选择器
 * Created by dogn on 2016/6/4.
 */
;
(function ($, window, document, ChineseDistricts) {

    if (typeof ChineseDistricts === 'undefined') {
        throw new Error('The file "area-picker.data.js" must be included first!');
    }

    var NAMESPACE = 'areapicker';
    var EVENT_CHANGE = 'change.' + NAMESPACE;
    var PROVINCE = 'province';
    var CITY = 'city';
    var DISTRICT = 'district';

    var AreaPicker = function (ele, opt) {
        this.$element = ele,
        this.defaults = {
            placeholder: '请选择省/市/区',
            level: 'district'
        },
        this.dems=[PROVINCE,CITY,DISTRICT],
        this.active = false,
        this.options = $.extend({}, this.defaults, opt);
        this.init();
    }

    AreaPicker.prototype = {
        //初始化
        init: function () {
            this.render();
            this.bind();
        },
        //渲染
        render: function(){
            var p = this.getPosition(),
                placeholder = this.$element.attr('placeholder') || this.options.placeholder,
                textspan = '<span class="area-picker-span" style="' +
                    this.getWidthStyle(p.width) + 'height:' +
                    p.height + 'px;line-height:' + (p.height - 1) + 'px;">' +
                    (placeholder ? '<span class="placeholder">' + placeholder + '</span>' : '') +
                    '<span class="title"></span><span class="arrow"></span>' + '</span>',
                dropdown = '<div class="area-picker-dropdown" style="left:0px;top:100%;' +
                    this.getWidthStyle(p.width, true) + '">' +
                    '<div class="area-select-wrap">' +
                    '<div class="area-select-tab">' +
                    '<a class="active" data-count="province">省份</a><a data-count="city">城市</a><a data-count="district">区县</a></div>' +
                    '<div class="area-select-content">' +
                    '<div class="area-select province" data-count="province"></div>'+
                    '<div class="area-select city" data-count="city"></div>'+
                    '<div class="area-select district" data-count="district"></div>'+
                    '</div></div>';

            this.$element.addClass('area-picker-input');
            this.$textspan = $(textspan).insertAfter(this.$element);
            this.$dropdown = $(dropdown).insertAfter(this.$textspan);
            var $select = this.$dropdown.find('.area-select');
            $.each(this.dems, $.proxy(function (i, type) {
                this['$' + type] = $select.filter('.' + type + '');
            }, this));
            this.refresh();
        },
        //刷新
        refresh: function(force){
            var $select = this.$dropdown.find('.area-select');
            $select.data('item', null);
            // parse value from value of the target $element
            var val = this.$element.val() || '';
            val = val.split('/');
            $.each(this.dems, $.proxy(function (i, type) {
                if (val[i] && i < val.length) {
                    this.options[type] = val[i];
                } else if (force) {
                    this.options[type] = '';
                }
                this.output(type);
            }, this));
            this.tab(PROVINCE);
            this.feedText();
            this.feedVal();
        },
        //得到位置、宽、高
        getPosition: function(){
            var p, h, w, s, pw;
            p = this.$element.position();
            s = this.getSize(this.$element);
            h = s.height;
            w = s.width;
            if (this.options.responsive) {
                pw = this.$element.offsetParent().width();
                if (pw) {
                    w = w / pw;
                    if (w > 0.99) {
                        w = 1;
                    }
                    w = w * 100 + '%';
                }
            }
            return {
                top: p.top || 0,
                left: p.left || 0,
                height: h,
                width: w
            };
        },
        getSize: function ($dom) {
            var $wrap, $clone, sizes;
            if (!$dom.is(':visible')) {
                $wrap = $("<div />").appendTo($("body"));
                $wrap.css({
                    "position": "absolute !important",
                    "visibility": "hidden !important",
                    "display": "block !important"
                });

                $clone = $dom.clone().appendTo($wrap);

                sizes = {
                    width: $clone.outerWidth(),
                    height: $clone.outerHeight()
                };

                $wrap.remove();
            } else {
                sizes = {
                    width: $dom.outerWidth(),
                    height: $dom.outerHeight()
                };
            }

            return sizes;
        },
        getWidthStyle: function (w, dropdown) {
            if (this.options.responsive && !$.isNumeric(w)) {
                return 'width:' + w + ';';
            } else {
                return 'width:' + (dropdown ? Math.max(320, w) : w) + 'px;';
            }
        },
        bind: function () {
            var $this = this;
            $(document).on('click', (this._mouteclick = function (e) {
                var $target = $(e.target);
                var $dropdown, $span, $input;
                if ($target.is('.area-picker-span')) {
                    $span = $target;
                } else if ($target.is('.area-picker-span *')) {
                    $span = $target.parents('.area-picker-span');
                }
                if ($target.is('.area-picker-input')) {
                    $input = $target;
                }
                if ($target.is('.area-picker-dropdown')) {
                    $dropdown = $target;
                } else if ($target.is('.area-picker-dropdown *')) {
                    $dropdown = $target.parents('.area-picker-dropdown');
                }
                if ((!$input && !$span && !$dropdown) ||
                    ($span && $span.get(0) !== $this.$textspan.get(0)) ||
                    ($input && $input.get(0) !== $this.$element.get(0)) ||
                    ($dropdown && $dropdown.get(0) !== $this.$dropdown.get(0))) {
                    $this.close(true);
                }
            }));
            this.$element.on('change', (this._changeElement = $.proxy(function () {
                this.close(true);
                this.refresh(true);
            }, this))).on('focus', (this._focusElement = $.proxy(function () {
                this.needBlur = true;
                this.open();
            }, this))).on('blur', (this._blurElement = $.proxy(function () {
                if (this.needBlur) {
                    this.needBlur = false;
                    this.close(true);
                }
            }, this)));
            this.$textspan.on('click', function (e) {
                var $target = $(e.target), type;
                $this.needBlur = false;
                if ($target.is('.select-item')) {
                    type = $target.data('count');
                    $this.open(type);
                } else {
                    if ($this.$dropdown.is(':visible')) {
                        $this.close();
                    } else {
                        $this.open();
                    }
                }
            }).on('mousedown', function () {
                $this.needBlur = false;
            });
            this.$dropdown.on('click', '.area-select a', function () {
                var $select = $(this).parents('.area-select');
                var $active = $select.find('a.active');
                var last = $select.next().length === 0;
                $active.removeClass('active');
                $(this).addClass('active');
                if ($active.data('id') !== $(this).data('id')) {
                    $select.data('item', {
                        address: $(this).attr('title'), code: $(this).data('id')
                    });
                    $(this).trigger(EVENT_CHANGE);
                    $this.feedText();
                    $this.feedVal();
                    if (last) {
                        $this.close();
                    }
                }
            }).on('click', '.area-select-tab a', function () {
                if (!$(this).hasClass('active')) {
                    var type = $(this).data('count');
                    $this.tab(type);
                }
            }).on('mousedown', function () {
                $this.needBlur = false;
            });

            if (this.$province) {
                this.$province.on(EVENT_CHANGE, (this._changeProvince = $.proxy(function () {
                    this.output(CITY);
                    this.output(DISTRICT);
                    this.tab(CITY);
                }, this)));
            }

            if (this.$city) {
                this.$city.on(EVENT_CHANGE, (this._changeCity = $.proxy(function () {
                    this.output(DISTRICT);
                    this.tab(DISTRICT);
                }, this)));
            }
        },
        open: function (type) {
            type = type || PROVINCE;
            this.$dropdown.show();
            this.$textspan.addClass('open').addClass('focus');
            this.tab(type);
        },
        close: function (blur) {
            this.$dropdown.hide();
            this.$textspan.removeClass('open');
            if (blur) {
                this.$textspan.removeClass('focus');
            }
        },
        unbind: function () {

            $(document).off('click', this._mouteclick);

            this.$element.off('change', this._changeElement);
            this.$element.off('focus', this._focusElement);
            this.$element.off('blur', this._blurElement);

            this.$textspan.off('click');
            this.$textspan.off('mousedown');

            this.$dropdown.off('click');
            this.$dropdown.off('mousedown');

            if (this.$province) {
                this.$province.off(EVENT_CHANGE, this._changeProvince);
            }

            if (this.$city) {
                this.$city.off(EVENT_CHANGE, this._changeCity);
            }
        },
        getText:function(){
            var text = '';
            this.$dropdown.find('.area-select')
                .each(function () {
                    var item = $(this).data('item'),
                        type = $(this).data('count');
                    if (item) {
                        text += ($(this).hasClass('province') ? '' : '/') + '<span class="select-item" data-count="' +
                            type + '" data-id="' + item.id + '">' + item.name + '</span>';
                    }
                });
            return text;
        },
        feedText: function () {
            var text = this.getText();
            if (text) {
                this.$textspan.find('>.placeholder').hide();
                this.$textspan.find('>.title').html(this.getText()).show();
            } else {
                this.$textspan.find('>.placeholder').text(this.getPlaceHolder()).show();
                this.$textspan.find('>.title').html('').hide();
            }
        },
        getPlaceHolder: function () {
            return this.$element.attr('placeholder') || this.options.placeholder;
        },
        feedVal: function () {
            this.$element.val(this.getVal());
        },
        getVal: function () {
            var text = '';
            this.$dropdown.find('.area-select')
                .each(function () {
                    var item = $(this).data('item');
                    if (item) {
                        text += ($(this).hasClass('province') ? '' : '/') + item.address;
                    }
                });
            return text;
        },
        output: function (type) {
            var options = this.options;
            var $select = this['$' + type];
            var data = [];
            var item;
            var districts;
            var code;
            var matched = null;
            var value;

            if (!$select || !$select.length) {
                return;
            }
            item = $select.data('item');
            value = (item ? item.address : null) || options[type];
            code = (
                type === PROVINCE ? 0 :
                    type === CITY ? this.$province && this.$province.find('.active').data('id') :
                        type === DISTRICT ? this.$city && this.$city.find('.active').data('id') : code
            );

            districts = $.isNumeric(code) ? this.getDistrictsByPid(ChineseDistricts,code) : null;

            if ($.isArray(districts)) {
                data = districts;
            }
            $select.html(this.getList(data, type));
            $select.data('item', matched);
        },
        getDistrictsByPid: function(ChineseDistricts,pid){
            var districts = [];
            $.each(ChineseDistricts,function(i,n){
                if(n.parentId==pid){
                    districts.push(n);
                }
            });
            return districts;
        },
        getList: function (data) {
            var list = [];
            $.each(data, function (i, n) {
                list.push(
                    '<a' +
                    ' title="' + (n.name || '') + '"' +
                    ' data-id="' + (n.id || '') + '"' +
                    ' class="' + (n.selected ? ' active' : '') +
                    '">'+(n.name || '')+'</a>');
            });
            return list.join('');
        },
        tab:function(type){
            var $selects = this.$dropdown.find('.area-select');
            var $tabs = this.$dropdown.find('.area-select-tab > a');
            var $select = this['$' + type];
            var $tab = this.$dropdown.find('.area-select-tab > a[data-count="' + type + '"]');
            if ($select) {
                $selects.hide();
                $select.show();
                $tabs.removeClass('active');
                $tab.addClass('active');
            }
        },
        reset: function () {
            this.$element.val(null).trigger('change');
        },
        destroy: function () {
            this.unbind();
            this.$element.removeData(NAMESPACE).removeClass('area-picker-input');
            this.$textspan.remove();
            this.$dropdown.remove();
        }
    }

    $.fn.areapicker = function (options) {
        return new AreaPicker(this, options);
    }

    $(function () {
        $('[data-toggle="area-picker"]').areapicker();
    });
})(jQuery, window, document, ChineseDistricts);